using Godot;
using System;
using CurrentGame.GUI;
using System.Collections.Generic;
using Godot.Collections;


public partial class GamePlayGui : Control
{
	[Signal]
	public delegate void InteractionPressedEventHandler();
	[Signal]
	public delegate void SingleLineFinishedEventHandler();
	[Signal]
	public delegate void DialogueBoxFinishedEventHandler();

	[Export]
	public bool CinematicMode
	{
		get => _cinematicMode;
		set
		{
			if (_cinematicAnimationTree != null)
			{
				_cinematicMode = value;
				_cinematicAnimationTree.DecorationActivated = value;
			}
		}
	}
	private bool _cinematicMode = false;

	[Export]
	public CinematicCamera CameraNode { get; set; }

	[Export]
	public Vector2 GuiSize { get; set; } = new Vector2(1920, 1080);

	[Export]
	public float FloatSpeed { get; set; } = 10;


	// Child node reference
	private CinematicDecorationAnimTree _cinematicAnimationTree;
	private InteractionTip _interactionTip;
	private Control _floatingAnchor;
	private Node2D _currentPositionNode;
	private SingleLineText _singleLineLabel;
	private DialogueBox _dialogueBox;
	private PlacementHint _placementHint;

	// Floating Anchor
	private Vector2 _currentPosition;

	// Multiple display
	private bool _multipleDisplay = false;
	private List<string> _multipleText;
	private List<Vector3> _multipleTextConfig;
	private int _multipleTextIter = 0;


	public override void _Ready()
	{
		_cinematicAnimationTree = GetNode<CinematicDecorationAnimTree>(
			"CinematicDecoration/AnimationPlayer/AnimationTree");
		_interactionTip = GetNode<InteractionTip>("FloatAnchor/InteractionTip");
		_floatingAnchor = GetNode<Control>("FloatAnchor");
		_singleLineLabel = GetNode<SingleLineText>("FloatAnchor/TextLabel");
		_dialogueBox = GetNode<DialogueBox>("DialogueBox");
		_placementHint = GetNode<PlacementHint>("PlaceHint");
	}

	public override void _PhysicsProcess(double delta)
	{
		if (_currentPositionNode != null)
		{
			_currentPosition = _currentPosition.MoveToward(
				GlobalToUi(_currentPositionNode.GlobalPosition), FloatSpeed * (float)delta);
			_floatingAnchor.Position = _currentPosition;
		}
	}


	// Export interfaces
	public Vector2 GlobalToUi(Vector2 globalPosition)
	{
		return GuiSize * 0.5f + (globalPosition - CameraNode.GlobalPosition) * CameraNode.Zoom;
    }

	// Floating anchor
	public void SetFloatingAnchor(Node2D node)
	{
		_currentPositionNode = node;
		_currentPosition = GlobalToUi(_currentPositionNode.GlobalPosition);
		_floatingAnchor.Position = _currentPosition;
		_floatingAnchor.ResetPhysicsInterpolation();
	}

	public void ResetFloatingAnchor()
	{
		_currentPositionNode = null;
	}


	// Interaction Tip
	public void ShowInteractionTips(string tipText)
	{
		_interactionTip.DisplayText = tipText;
		_interactionTip.ShowTip();
	}

	public void HideInteractionTips()
	{
		_interactionTip.HideTip();
	}

	// Single Line Text
	private void ShowSingleLineText(string text, float stay, float typeSpeed, float fadeSpeed)
	{
		_singleLineLabel.EnableTyping = typeSpeed > 0.0f;
		_singleLineLabel.TypingSpeed = (typeSpeed < 0.0f ? 20.0f : typeSpeed);
		_singleLineLabel.EnableFade = fadeSpeed > 0.0f;
		_singleLineLabel.FadeFactor = (fadeSpeed < 0.0f ? 0.05f : fadeSpeed);
		_singleLineLabel.StayDuration = stay;
		_singleLineLabel.ShowText = text;
	}

	public void ShowMultipleText(List<string> texts, List<Vector3> config)
	{
		_multipleDisplay = true;
		_multipleText = texts;
		_multipleTextConfig = config;
		_multipleTextIter = 1;
		var c = config[0];
		ShowSingleLineText(texts[0], c.X, c.Y, c.Z);
	}

	// Dialogue
	public void OpenDialogueBox()
	{
		_dialogueBox.Opened = true;
	}

	public void ChangeDialogueContent(Array<string> contents)
	{
		_dialogueBox.ShowContent = contents;
	}

	// Placement hints
	public void ShowPlacementHint()
	{
		_placementHint.EnableHint();
	}
	
	public void ChangePlacementHint(string text)
	{
		_placementHint.HintText = text;
	}

	public void HidePlacementHint()
	{
		_placementHint.DisableHint();
	}

	public void SetPlacementHintAnchor(Node2D node)
	{
		_placementHint.SetAnchor(node);
	}

	// GODOT Signals
	private void Signal_InteractionTipActivated()
	{
		EmitSignal(SignalName.InteractionPressed);
	}

	private void Signal_SingleLineFinished()
	{
		if (!_multipleDisplay) return;

		if (_multipleTextIter >= _multipleText.Count)
		{
			EmitSignal(SignalName.SingleLineFinished);
			_multipleDisplay = false;
		}
		else
		{
			var config = _multipleTextConfig[_multipleTextIter];
			ShowSingleLineText(_multipleText[_multipleTextIter], config.X, config.Y, config.Z);
            _multipleTextIter += 1;
		}
	}

	private void Signal_DialogueBoxFinished()
	{
		EmitSignal(SignalName.DialogueBoxFinished);
	}

	private void Signal_PauseStateChanged(bool paused)
	{
		if (!paused)
		{
			// game continue
			_dialogueBox.ReGrabFocus();
			_interactionTip.ReGrabFocus();
		}
	}
}
